"""
release = 1.002 ((05.02.2015)
Вовращает ссылку на БД СУБД MySQL.
"""

import os
import sys
import configparser

from PyQt5.QtSql import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *


class Db(object):


    def __init__(self, type='QSQLITE', connectionName=None):
        super(Db, self).__init__()

        """ ДОБАВЛЯЕМ НОВОЕ СОЕДИЕНИЕ В СПИСОК СОЕДИНЕНИЙ."""
        
        if connectionName is None:
            db = QSqlDatabase.addDatabase(type)
        else:
            db = QSqlDatabase.addDatabase(type, connectionName)
        self._db = db
        
        
    def __del__(self):
    
        """ УДАЛЯЕМ СОЕДИНЕНИЕ ИЗ СПИСКА СОЕДИНЕНИЙ."""
        
        self._db.close()
        connectionName = self._db.connectionName()
        del self._db
        QSqlDatabase.removeDatabase(connectionName)

        
    def open(self, ini_file):
        """ ОТКРЫВАЕМ БД С ПАРАМЕТРАМИ ИЗ INI ФАЙЛА.
        -- Читаем ini файл. Если секции SERVER нет, то создаём.
        -- Открываем БД. Если открылась - УДАЧНО.
        -- Соединение не удалось. Создаём диалог для интерактивного соединения.
        -- Удалось открыть интерактивно - УДАЧНО. Сохраняем параметры соединения 
           в ini файле."""
        
        ini_file = "{}\\{}".format(os.getenv('APPDATA'), ini_file)
        self._conf = configparser.ConfigParser()
        self._conf.read(ini_file)
        if not ('SERVER' in self._conf):
            self._conf['SERVER'] = {}

        while 1:
            if self._open():
                result = True
                break
    
            dialog = DialogServer(self._conf)
            if not dialog.exec_():
                result = False
                break

        if result:
            with open(ini_file, 'w') as file_ini:
                self._conf.write(file_ini)
            return True
        
        
    def _open(self):

        """ ОТКРЫВАЕТ БД.
        -- Подставляем параметры соединения из секции SERVER файла ini.
        -- Открываем БД. Возвращаем ссылку на соединение.
        -- Не открылось - сообщение об ошибке."""
        
        server = self._conf['SERVER']
        db = self._db
        db.setHostName(server.get('host_name'))
        db.setDatabaseName(server.get('data_base'))
        db.setUserName(server.get('user'))
        db.setPassword(server.get('password'))
        
        if db.open():
            return True
            
        error = db.lastError()
        num_error = error.number()
        if num_error == 1044:
            message = ("Введите правильное имя базы данных. "
                "Обратитесь за помощью к системному администратору.")
        elif num_error == 1045:
            message = ("Введите правильное имя пользователя и пароль. "
                "Обратитесь за помощью к системному администратору.")
        elif num_error in (2003, 2005):
            message = ("Введите правильное сетевое имя сервера или IP адрес. "
                "Обратитесь за помощью к системному администратору.")
        else:
            message = ("Код ошибки сервера: {}. Оригинальное сообщение: {}. "
                "Обратитесь за помощью к программисту."
                .format(num_error, error.text()))
        report = QMessageBox()
        report.setIcon(QMessageBox.Critical) 
        report.setWindowTitle("НЕТ СОЕДИНЕНИЯ С БАЗОЙ ДАННЫХ")
        report.setText(message)
        report.setWindowIcon(QIcon("pict\\main.ico"))
        report.exec_()
        
        
class DialogServer(QDialog):

    """ ФОРМА ИНТЕРАКТИВНОГО СОЕДИНЕНИЯ С СЕРВЕРОМ."""

    def __init__(self, conf):
        super().__init__()

        self._conf = conf
        self.create_ui()
        
        
    def create_ui(self):

        """ СОЗДАНИЕ ФОРМЫ."""

        server = self._conf['SERVER']

        form = QFormLayout()
        
        self.edt_host_name = QLineEdit(server.get('host_name',''))
        form.addRow("Сервер", self.edt_host_name)
        
        self.edt_database = QLineEdit(server.get('data_base',''))
        self.edt_database.setReadOnly(True)
        form.addRow("База", self.edt_database)
        
        self.edt_user_name = QLineEdit(server.get('user',''))
        self.edt_user_name.setReadOnly(True)
        form.addRow("Логин", self.edt_user_name)
        
        self.edt_password = QLineEdit(server.get('password',''))
        self.edt_password.setReadOnly(True)
        form.addRow("Пароль", self.edt_password)
        
        btn_open = QPushButton('ОТКРЫТЬ БАЗУ ДАННЫХ')
        btn_open.setDefault(True)
        btn_open.clicked.connect(self.open)
        form.addRow(btn_open)
        
        self.btn_unlock = QPushButton('РАЗБЛОКИРОВАТЬ ПОЛЯ')
        self.btn_unlock.clicked.connect(self.unlock)
        form.addRow(self.btn_unlock)
        
        self.setLayout(form)
        self.setWindowTitle("ПАРАМЕТРЫ БД")
        self.setWindowIcon(QIcon('pict\\main.ico'))
        self.setMinimumWidth(200)

        self.edt_host_name.setFocus()

        
    def unlock(self):
    
        self.edt_database.setReadOnly(False)
        self.edt_user_name.setReadOnly(False)
        self.edt_password.setReadOnly(False)
        self.btn_unlock.hide()
    
    def open(self):
    
        """ НАЖАТИЕ КНОПКИ 'ОТКРЫТЬ БАЗУ ДАННЫХ'.
        -- Проверка заполнения полей. 
        -- Загрузка значений полей в переменную конфигурации.
        -- Открываем БД. Сохраняем ссылку на соединение в атрибутах."""
        
        if (not self.edt_host_name.text() or                                    
            not self.edt_database.text() or
            not self.edt_user_name.text() or
            not self.edt_password.text()):
            report = QMessageBox()
            report.setIcon(QMessageBox.Warning)
            report.setWindowTitle("НЕДОСТАТОЧНО ИНФОРМАЦИИ")
            report.setText("Все поля должны быть заполнены.")
            report.setWindowIcon(QIcon("pict\\main.ico"))
            report.exec_()
            return
            
        server = self._conf['SERVER']
        server['host_name'] = self.edt_host_name.text()                        
        server['data_base'] = self.edt_database.text()
        server['user'] = self.edt_user_name.text()
        server['password'] = self.edt_password.text()
        self.accept()    

        
    def closeEvent(self,е):
    
        """ НАЖАТА СИСТЕМНАЯ КНОПКА <ЗАКРЫТЬ ФОРМУ>  ."""
        
        self.reject()


if __name__ == '__main__':

    app = QApplication(sys.argv)
    
    db = get_db_mysql("test.ini")
    if db:
        QMessageBox.information(None, 'self-test', "Пройдено удачно.")
    else:
        QMessageBox.critical(None, 'self-test', "Завершилось ошибкой.")
